﻿using Client.Components.PrinterPanel;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Client.Components
{
    // TODO 优化加载等待时间 或者 在后台进行加载

    // V 2.0.4 - 2022-08-24 17:47:28
    // !!! Binding 与 UpdataData 不要混用 !!!
    // 修复赋值的Bug
    // 
    // V 2.0.3 - 2022-08-24 10:56:25
    // 1 修复数据错误红框的Bug - 在 Loaded 事件之前, 不检查 SelectedPrinter_Inner 与 SelectedPaperSize_Inner
    // 2 增加依赖属性 DefaultPrinterName, 可以用于读取配置文件的值 快速设置默认打印机
    //
    // V 2.0.2 - 2021-09-10 11:20:43
    // 1. 打印机ComboBox / 纸张ComboBox 增加 IsEditable = true ( 可以通过键盘录入值快速定位, 并且通过 Backspace 设置绑定值为 null )
    // 2. 增加 ComboBoxHeight 依赖属性, 调整所有 ComboBox 的高度, 默认 26d
    // 
    // V 2.0.1 - 2021-07-26 09:58:21
    // 修复选中刷新... 项, 出现的Bug
    // 
    // V 2.0.0 - 2021-07-04 22:34:58
    // 重写大部分功能
    // 
    // V 1.0.1 - 2019-03-15 12:05:01
    // 1. 修复选择打印机后没有自动选择纸张
    // 2. UI Combobox 文本对齐问题

    /// <summary>
    /// UcPrinterPanel
    /// </summary>
    public partial class UcPrinterPanel : UserControl, INotifyPropertyChanged, IDataErrorInfo
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public UcPrinterPanel()
        {
            InitializeComponent();
            this.Loaded += ucLoaded;
        }

        private void ucLoaded(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine($"UcPrinterPanel Loaded - IsLoaded {this.IsLoaded}");
            init();
        }

        void init()
        {
            System.Diagnostics.Debug.WriteLine("init 方法");

            if (string.IsNullOrWhiteSpace(PriorityPrinterListStr) == false)
            {
                this.PriorityPrinterList = PriorityPrinterListStr.Split(',').Select(i => i.Trim()).Where(i => string.IsNullOrWhiteSpace(i) == false).ToList();
            }
            else
            {
                this.PriorityPrinterList = new List<string>();
            }


            if (string.IsNullOrWhiteSpace(PriorityPaperSizeListStr) == false)
            {
                this.PriorityPaperSizeList = PriorityPaperSizeListStr.Split(',').Select(i => i.Trim()).Where(i => string.IsNullOrWhiteSpace(i) == false).ToList();
            }
            else
            {
                this.PriorityPaperSizeList = new List<string>();
            }

            if (this.PrinterList == null)
            {
                System.Diagnostics.Debug.WriteLine("UcPrinterPanel 检测 this.PrinterList == null");

                this.PrinterList = PrinterUtils.PrinterOrderBy
                (
                    printerList: PrinterUtils.GetPrinterList(isContainUpdateListItem: true),
                    priorityPrinterList: this.PriorityPrinterList,
                    priorityPaperList: this.PriorityPaperSizeList
                );

                System.Diagnostics.Debug.WriteLine("UcPrinterPanel this.PrinterList 附默认值");
            }

            if (this.SelectedPrinter_Inner == null)
            {
                System.Diagnostics.Debug.WriteLine("UcPrinterPanel 检测 this.SelectedPrinter_Inner == null");

                // 设置默认打印机
                Printer match = null;

                if (string.IsNullOrEmpty(this.DefaultPrinterName) == false)
                {
                    // 自定义默认选中打印机
                    match = this.PrinterList.FirstOrDefault(i => i.DisplayName == this.DefaultPrinterName);
                }

                if (match == null)
                {
                    // 获取系统默认打印机
                    var defaultPrinterName = PrinterUtils.GetDefaultPrinterName();
                    match = this.PrinterList.FirstOrDefault(i => i.DisplayName == defaultPrinterName);
                }

                if (match != null)
                {
                    System.Diagnostics.Debug.WriteLine("UcPrinterPanel 检测 this.SelectedPrinter_Inner == null");

                    this.SelectedPrinter_Inner = match;

                    System.Diagnostics.Debug.WriteLine($"UcPrinterPanel this.SelectedPrinter_Inner 设置为 {match.DisplayName}");

                    // 设置默认 PaperSize
                    if (string.IsNullOrEmpty(this.DefaultPaperSize) == false)
                    {
                        System.Diagnostics.Debug.WriteLine("UcPrinterPanel 检测 发现 PaperSize 有默认值");

                        try
                        {
                            this.SelectedPaperSize_Inner = match.PaperSizeList.First(i => i.DisplayName == this.DefaultPaperSize);
                            System.Diagnostics.Debug.WriteLine($"UcPrinterPanel 设置 this.SelectedPaperSize_Inner 为 {this.SelectedPaperSize_Inner.DisplayName}");
                        }
                        catch (Exception ex)
                        {
                            System.Diagnostics.Debug.WriteLine($"error UcPrinterPanel 设置 this.SelectedPaperSize_Inner 捕获异常 {ex.Message}");
                        }
                    }

                }
            }
        }


        #region [DP] InputControlsHeight - 批量调整所有 输入/选择控件 高度

        public static readonly DependencyProperty InputControlsHeightProperty = DependencyProperty.Register
        (
            name: "InputControlsHeight",
            propertyType: typeof(double),
            ownerType: typeof(UcPrinterPanel),
            validateValueCallback: null,
            typeMetadata: new PropertyMetadata
            (
                defaultValue: 26d,
                propertyChangedCallback: null,
                coerceValueCallback: null
            )
        );

        public double InputControlsHeight
        {
            get { return (double)GetValue(InputControlsHeightProperty); }
            set { SetValue(InputControlsHeightProperty, value); }
        }

        #endregion

        #region [DP] IsValidated -- 验证通过, 所有选项都符合验证

        public static readonly DependencyProperty IsValidatedProperty = DependencyProperty.Register
        (
            name: "IsValidated",
            propertyType: typeof(bool),
            ownerType: typeof(UcPrinterPanel),
            validateValueCallback: null,
            typeMetadata: new PropertyMetadata
            (
                defaultValue: false,
                propertyChangedCallback: null,
                coerceValueCallback: null
            )
        );

        public bool IsValidated
        {
            get { return (bool)GetValue(IsValidatedProperty); }
            set { SetValue(IsValidatedProperty, value); }
        }

        #endregion

        #region [DP] PriorityPrinterListStr

        public static readonly DependencyProperty PriorityPrinterListStrProperty = DependencyProperty.Register
        (
            name: "PriorityPrinterListStr",
            propertyType: typeof(string),
            ownerType: typeof(UcPrinterPanel),
            validateValueCallback: null,
            typeMetadata: new PropertyMetadata
            (
                defaultValue: null,
                propertyChangedCallback: null,
                coerceValueCallback: null
            )
        );

        public string PriorityPrinterListStr
        {
            get { return (string)GetValue(PriorityPrinterListStrProperty); }
            set { SetValue(PriorityPrinterListStrProperty, value); }
        }

        #endregion

        /// <summary>
        /// 打印机优先列表
        /// </summary>
        public List<string> PriorityPrinterList;

        #region [DP] PriorityPaperSizeListStr

        public static readonly DependencyProperty PriorityPaperSizeListStrProperty = DependencyProperty.Register
        (
            name: "PriorityPaperSizeListStr",
            propertyType: typeof(string),
            ownerType: typeof(UcPrinterPanel),
            validateValueCallback: null,
            typeMetadata: new PropertyMetadata
            (
                defaultValue: null,
                propertyChangedCallback: null,
                coerceValueCallback: null
            )
        );

        public string PriorityPaperSizeListStr
        {
            get { return (string)GetValue(PriorityPaperSizeListStrProperty); }
            set { SetValue(PriorityPaperSizeListStrProperty, value); }
        }

        #endregion

        /// <summary>
        /// 纸张优先
        /// </summary>
        public List<string> PriorityPaperSizeList;





        #region [DP] PrinterList

        public static readonly DependencyProperty PrinterListProperty = DependencyProperty.Register
        (
            name: "PrinterList",
            propertyType: typeof(List<Printer>),
            ownerType: typeof(UcPrinterPanel),
            validateValueCallback: null,
            typeMetadata: new PropertyMetadata
            (
                defaultValue: null,
                propertyChangedCallback: null,
                coerceValueCallback: null
            )
        );

        public List<Printer> PrinterList
        {
            get { return (List<Printer>)GetValue(PrinterListProperty); }
            set { SetValue(PrinterListProperty, value); }
        }

        #endregion

        private Printer _SelectedPrinter_Inner;
        public Printer SelectedPrinter_Inner
        {
            get { return _SelectedPrinter_Inner; }
            set
            {
                _SelectedPrinter_Inner = value;
                this.OnPropertyChanged(nameof(SelectedPrinter_Inner));

                this.SelectedPrinter = value; // !!!! 向对外绑定的SelectedPrinter赋值
            }
        }

        /// <summary>
        /// 控件外部静默赋值
        /// </summary>
        /// <param name="value"></param>
        public void SetSelectedPrinter_Inner_Slient(Printer value)
        {
            _SelectedPrinter_Inner = value;
            this.OnPropertyChanged(nameof(SelectedPrinter_Inner));
        }

        #region [DP] SelectedPrinter

        public static readonly DependencyProperty SelectedPrinterProperty = DependencyProperty.Register
        (
            name: "SelectedPrinter",
            propertyType: typeof(Client.Components.PrinterPanel.Printer),
            ownerType: typeof(UcPrinterPanel),
            validateValueCallback: null,
            typeMetadata: new PropertyMetadata
            (
                defaultValue: null,
                propertyChangedCallback: onSelectedPrinter_PropertyChangedCallback,
                coerceValueCallback: null
            )
        );

        public Client.Components.PrinterPanel.Printer SelectedPrinter
        {
            get { return (Client.Components.PrinterPanel.Printer)GetValue(SelectedPrinterProperty); }
            set { SetValue(SelectedPrinterProperty, value); }
        }

        public static void onSelectedPrinter_PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is UcPrinterPanel target)
            {
                if (target.SelectedPrinter_Inner == null && e.NewValue is Printer vvv) // 控件外赋值初始值
                {
                    target.SetSelectedPrinter_Inner_Slient(vvv);
                    target.SelectedPaperSize_Inner = target.SelectedPrinter_Inner.PaperSizeList[0];
                    return;
                }

                if (e.NewValue != null && e.NewValue is Printer value && value.DisplayName == PrinterUtils.UpdateItem)
                {
                    // 选择了 刷新 项
                    var temp = PrinterUtils.GetPrinterList(isContainUpdateListItem: true);
                    target.PrinterList = PrinterUtils.PrinterOrderBy(printerList: temp, priorityPrinterList: target.PriorityPrinterList, priorityPaperList: target.PriorityPaperSizeList);
                    return;
                }

                if (target.SelectedPrinter_Inner != null)
                {
                    target.SelectedPaperSize_Inner = target.SelectedPrinter_Inner.PaperSizeList[0];
                }
            }
        }

        #endregion

        #region [DP] DefaultPrinterName

        public static readonly DependencyProperty DefaultPrinterNameProperty = DependencyProperty.Register
        (
            name: "DefaultPrinterName",
            propertyType: typeof(string),
            ownerType: typeof(UcPrinterPanel),
            validateValueCallback: null,
            typeMetadata: new PropertyMetadata
            (
                defaultValue: null,
                propertyChangedCallback: null,
                coerceValueCallback: null
            )
        );

        public string DefaultPrinterName
        {
            get { return (string)GetValue(DefaultPrinterNameProperty); }
            set { SetValue(DefaultPrinterNameProperty, value); }
        }

        #endregion

        #region [DP] DefaultPaperSize

        public static readonly DependencyProperty DefaultPaperSizeProperty = DependencyProperty.Register
        (
            name: "DefaultPaperSize",
            propertyType: typeof(string),
            ownerType: typeof(UcPrinterPanel),
            validateValueCallback: null, // new ValidateValueCallback((toValidate) => { return true; }),
            typeMetadata: new PropertyMetadata
            (
                defaultValue: null,
                propertyChangedCallback: null,
                coerceValueCallback: null
            )
        );

        public string DefaultPaperSize
        {
            get { return (string)GetValue(DefaultPaperSizeProperty); }
            set { SetValue(DefaultPaperSizeProperty, value); }
        }

        #endregion




        // PaperSizeList 在 XAML 采用控件直接绑定的方式
        //public List<PaperSize> PaperSizeList

        #region [DP] SelectedPaperSize

        public static readonly DependencyProperty SelectedPaperSizeProperty = DependencyProperty.Register
        (
            name: "SelectedPaperSize",
            propertyType: typeof(PaperSize),
            ownerType: typeof(UcPrinterPanel),
            validateValueCallback: null,
            typeMetadata: new PropertyMetadata
            (
                defaultValue: null,
                propertyChangedCallback: null,
                coerceValueCallback: null
            )
        );

        public PaperSize SelectedPaperSize
        {
            get { return (PaperSize)GetValue(SelectedPaperSizeProperty); }
            set { SetValue(SelectedPaperSizeProperty, value); }
        }

        #endregion



        private PaperSize _SelectedPaperSize_Inner;
        public PaperSize SelectedPaperSize_Inner
        {
            get { return _SelectedPaperSize_Inner; }
            set
            {
                _SelectedPaperSize_Inner = value;
                this.OnPropertyChanged(nameof(SelectedPaperSize_Inner));

                this.SelectedPaperSize = value;
            }
        }

        #region [DP] PaperSizeVisibility

        public static readonly DependencyProperty PaperSizeVisibilityProperty = DependencyProperty.Register
        (
            name: "PaperSizeVisibility",
            propertyType: typeof(Visibility),
            ownerType: typeof(UcPrinterPanel),
            validateValueCallback: null,
            typeMetadata: new PropertyMetadata
            (
                defaultValue: Visibility.Visible,
                propertyChangedCallback: null, // onPaperSizeVisibility_PropertyChangedCallback,
                coerceValueCallback: null
            )
        );

        public Visibility PaperSizeVisibility
        {
            get { return (Visibility)GetValue(PaperSizeVisibilityProperty); }
            set { SetValue(PaperSizeVisibilityProperty, value); }
        }

        #endregion


        /// <summary>
        /// 更新UI数据
        /// </summary>
        /// <param name="printerDisplayName"></param>
        /// <param name="paperSizeDisplayName"></param>
        public void UpdateData(string printerDisplayName, string paperSizeDisplayName = null)
        {
            try
            {
                this.SelectedPrinter_Inner = this.PrinterList.First(i => i.DisplayName == printerDisplayName);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"error UcPrinterPanel - 更新 this.SelectedPrinter_Inner 捕获异常 {ex.Message}");

                if (this.PrinterList == null)
                {
                    System.Diagnostics.Debug.WriteLine("error UcPrinterPanel - 估计是未执行 init()");
                    this.DefaultPrinterName = printerDisplayName;

                    if (string.IsNullOrEmpty(paperSizeDisplayName) == false)
                    {
                        this.DefaultPaperSize = paperSizeDisplayName;
                    }

                    return;
                }
            }

            if (string.IsNullOrEmpty(paperSizeDisplayName) == false)
            {
                try
                {
                    this.SelectedPaperSize_Inner = this.SelectedPrinter_Inner.PaperSizeList.First(i => i.DisplayName == paperSizeDisplayName);
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine($"error UcPrinterPanel - 更新 this.SelectedPaperSize_Inner 捕获异常 {ex.Message}");

                    if (this.PrinterList == null)
                    {
                        System.Diagnostics.Debug.WriteLine("error UcPrinterPanel - 估计是未执行 init()");
                        this.DefaultPaperSize = paperSizeDisplayName;
                    }
                }
            }
        }

        #region INotifyPropertyChanged成员

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion

        #region IDataInfo

        public virtual bool _IsValidated_
        {
            get
            {
                return this.ErrorCollection.Count == 0;
            }
        }

        public string Error
        {
            get
            {
                return $"共 {this.ErrorCollection.Values.Count} 个错误";
            }
        }

        public System.Collections.Generic.Dictionary<string, string> ErrorCollection { get; private set; } = new System.Collections.Generic.Dictionary<string, string>();

        protected void executeErrorCollection(string columnName, string errorMsg)
        {
            if (ErrorCollection.ContainsKey(columnName))
            {
                if (string.IsNullOrWhiteSpace(errorMsg))
                {
                    ErrorCollection.Remove(columnName);
                }
                else
                {
                    ErrorCollection[columnName] = errorMsg;
                }
            }
            else
            {
                if (string.IsNullOrWhiteSpace(errorMsg) == false)
                {
                    ErrorCollection.Add(columnName, errorMsg);
                }
            }

            IsValidated = _IsValidated_;

            this.OnPropertyChanged(nameof(ErrorCollection));
            this.OnPropertyChanged(nameof(Error));
            this.OnPropertyChanged(nameof(_IsValidated_));
        }

        /// <summary>
        /// 判断errorMessage, 若符合条件则添加到 validationResultList 中
        /// </summary>
        /// <param name="validationResultList"></param>
        /// <param name="errorMessage"></param>
        protected void addValidationResult
        (
            ICollection<System.ComponentModel.DataAnnotations.ValidationResult> validationResultList,
            string errorMessage
        )
        {
            if (string.IsNullOrEmpty(errorMessage) == false)
            {
                validationResultList.Add(new System.ComponentModel.DataAnnotations.ValidationResult(errorMessage));
            }
        }

        public virtual string this[string columnName]
        {
            get
            {
                string errorMsg = null;

                // Step 1 根据 System.ComponentModel.DataAnnotations 进行校验
                var vc = new System.ComponentModel.DataAnnotations.ValidationContext(this, null, null);
                vc.MemberName = columnName;
                var validationResults = new List<System.ComponentModel.DataAnnotations.ValidationResult>();
                System.ComponentModel.DataAnnotations.Validator.TryValidateProperty
                (
                    value: this.GetType().GetProperty(columnName).GetValue(this, null),
                    validationContext: vc,
                    validationResults: validationResults
                );

                // Step 2 根据额外编写的校验逻辑进行校验
                switch (columnName)
                {
                    case nameof(SelectedPrinter_Inner):
                        checkSelectedPrinter(validationResults);
                        break;
                    case nameof(SelectedPaperSize_Inner):
                        checkSelectedPaperSize(validationResults);
                        break;

                    default:
                        break;
                }

                if (validationResults.Count > 0)
                {
                    errorMsg = string.Join(";", validationResults);
                }

                executeErrorCollection(columnName, errorMsg);

                return errorMsg;
            }
        }

        void checkSelectedPrinter(List<System.ComponentModel.DataAnnotations.ValidationResult> l)
        {
            if (this.SelectedPrinter_Inner == null)
            {
                // 修复数据错误红框的Bug - 在 Loaded 事件之前, 不检查 SelectedPrinter_Inner 与 SelectedPaperSize_Inner
                if (IsLoaded == false) { return; }

                System.Diagnostics.Debug.WriteLine("error - checkSelectedPrinter == null");

                addValidationResult(l, "未选择打印机");
            }
            else if (this.PrinterList != null && this.PrinterList.Contains(this.SelectedPrinter_Inner) == false)
            {
                addValidationResult(l, "选中的打印机不在列表中");
            }
        }

        void checkSelectedPaperSize(List<System.ComponentModel.DataAnnotations.ValidationResult> l)
        {
            if (PaperSizeVisibility == Visibility.Visible)
            {
                if (this.SelectedPaperSize_Inner == null)
                {
                    // 修复数据错误红框的Bug - 在 Loaded 事件之前, 不检查 SelectedPrinter_Inner 与 SelectedPaperSize_Inner
                    if (IsLoaded == false) { return; }

                    addValidationResult(l, "未选择纸张");
                }
                //else if (this.PaperSizeList != null && this.PaperSizeList.Contains(this.SelectedPaperSize_Inner) == false)
                //{
                //    addValidationResult(l, "选中的纸张不在列表中");
                //}
                else if (this.SelectedPrinter_Inner != null && this.SelectedPrinter_Inner.PaperSizeList.Contains(this.SelectedPaperSize_Inner) == false)
                {
                    addValidationResult(l, "选中的纸张不在列表中");
                }
            }
        }

        #endregion
    }
}
